home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Moscow ML 1.31 / source code / mosml / src / toolssrc / Smltope.sml < prev   
Encoding:
Text File  |  1995-10-19  |  26.7 KB  |  764 lines  |  [TEXT/Moml]

  1. (* Smltop.sml *)
  2.  
  3. open List Obj BasicIO Nonstdio;
  4. open Miscsys Memory Fnlib Config Mixture Const Smlexc Smlprim;
  5. open Globals Location Units Types Smlperv Code_dec Emitcode Emit_phr Compiler;
  6. open Symtable Patch;
  7. open Rtvals Load_phr Exec_phr;
  8.  
  9. exception Already of string
  10. and NotYet of string
  11.  
  12. fun add_suffix name suffix =
  13.   if Filename.check_suffix name suffix
  14.   then (Filename.chop_suffix name suffix, name)
  15.   else (name, name ^ suffix)
  16. ;
  17.  
  18. (* Loading in core a compiled bytecode file *)
  19.  
  20. fun tryEvalLoad name =
  21.   let
  22.     val (simplename, filename) = add_suffix name ".uo"
  23.     val uname = normalizedUnitName(Filename.basename simplename)
  24.     val () =
  25.       if member uname reservedUnitNames then
  26.         raise Fail ("load: cannot load built-in unit "^uname)
  27.       else ()
  28.     val () =
  29.       (ignore (Hasht.find (!watchDog) uname);
  30.        raise Already uname)
  31.       handle Subscript => ()
  32.     val block_len = ref 0
  33.     val code = ref ""
  34.     val truename = find_in_path filename
  35.     val is = open_in_bin truename
  36.     val () =
  37.       let
  38.         val stop = input_binary_int is
  39.         val start = pos_in is
  40.         val code_len = stop - start
  41.         val () = (block_len := code_len + 1)
  42.         (* Now we have to check, whether the unit body is compatible *)
  43.         (* with its compiled signature and previously loaded units. *)
  44.         val () = seek_in is stop
  45.         val tables = (input_value is : compiled_unit_tables)
  46.         val () =
  47.           Hasht.apply (fn uname' => fn stamp' =>
  48.               let val stamp'' = Hasht.find (!watchDog) uname' in
  49.                 if stamp'' <> stamp' then
  50.                   raise Fail ("load: compiled body of unit "^uname^
  51.                      " is incompatible with previously loaded unit "^
  52.                      uname')
  53.                 else ()
  54.               end
  55.               handle Subscript => raise NotYet uname')
  56.             (#cu_mentions tables)
  57.         (* The following line will cause the compiled signature *)
  58.         (* to be put into the current table of unit signatures (if not there)! *)
  59.         val sig = (Hasht.find (!currentSigTable) uname
  60.                    handle Subscript => readSig uname)
  61.         prim_val set_nth_char_ : string -> int -> char -> unit
  62.                                                  = 3 "set_nth_char"
  63.       in
  64.         if #cu_sig_stamp tables <> getOption (!(#uStamp sig)) then
  65.            raise Fail ("load: compiled body of unit "^uname^
  66.                        " is incompatible with its compiled signature")
  67.         else ();
  68.         seek_in is start;
  69.         code := static_alloc (!block_len);
  70.         fast_really_input is (!code) 0 code_len;
  71.         (* `set_nth_char' must not check the length of buff, *)
  72.         (* because `code' is allocated outside the heap! *)
  73.         set_nth_char_ (!code) code_len (Char.chr Opcodes.STOP);
  74.         app
  75.           (fn phr =>
  76.             patch_object (!code) ((#cph_pos phr) - start) (#cph_reloc phr))
  77.           (rev (#cu_phrase_index tables));
  78.         exportPublicNames uname
  79.           (#cu_exc_ren_list tables) (#cu_val_ren_list tables);
  80.         Hasht.insert (!currentSigTable) uname sig;
  81.         Hasht.insert (!watchDog) uname (#cu_sig_stamp tables);
  82.         close_in is
  83.       end
  84.       handle x =>
  85.         (close_in is; raise x)
  86.     val res = do_code false (!code) 0 (!block_len)
  87.   in () end
  88. ;
  89.  
  90. fun evalLoad s =
  91.   (catch_interrupt false; tryEvalLoad s; catch_interrupt true)
  92.   handle
  93.        Io s =>
  94.          (catch_interrupt true; raise Fail ("load: "^s))
  95.      | Already uname =>
  96.          (catch_interrupt true;
  97.       raise Fail ("load: unit "^uname^" has been loaded already"))
  98.      | NotYet uname =>
  99.          (catch_interrupt true;
  100.       raise Fail ("load: unit "^uname^" is needed but not yet loaded"))
  101.      | Out_of_memory =>
  102.          (catch_interrupt true; raise Fail "load: out of memory")
  103.      | Toplevel =>
  104.          (catch_interrupt true;
  105.           raise Fail "load: unable to load")
  106.      | x => (catch_interrupt true; raise x)
  107. ;
  108.  
  109. (* A more user-friendly load function:
  110.    * does not fail when a unit has already been loaded;
  111.    * automatically loads any unit that a requested unit depends on.
  112. *)
  113.  
  114. fun smartEvalLoad s =
  115.     let fun tryload s pending =
  116.     (catch_interrupt false; tryEvalLoad s; catch_interrupt true)
  117.     handle
  118.     Io s =>
  119.         (catch_interrupt true; raise Fail ("load: "^s))
  120.       | Already _ =>
  121.         catch_interrupt true
  122.       | NotYet missing =>
  123.         (catch_interrupt true;
  124.          if member missing pending then
  125.          raise Fail ("load: unit " ^ missing ^
  126.                  " indirectly depends on itself")
  127.          else
  128.          (tryload missing (s :: pending);
  129.           tryload s pending))
  130.       | Out_of_memory =>
  131.         (catch_interrupt true; raise Fail "load: out of memory")
  132.       | Toplevel =>
  133.         (catch_interrupt true;
  134.          raise Fail "load: unable to load")
  135.       | x => (catch_interrupt true; raise x)
  136.     in tryload s [] end
  137. ;
  138.  
  139. fun protect_current_input fct =
  140.   let val saved_input_name = !input_name
  141.       and saved_input_stream = !input_stream
  142.       and saved_input_lexbuf = !input_lexbuf
  143.   in
  144.     (fct();
  145.      input_lexbuf := saved_input_lexbuf;
  146.      input_stream := saved_input_stream;
  147.      input_name := saved_input_name)
  148.     handle x =>
  149.       (input_lexbuf := saved_input_lexbuf;
  150.        input_stream := saved_input_stream;
  151.        input_name := saved_input_name;
  152.        raise x)
  153.   end
  154. ;
  155.  
  156. (* Loading an SML source file *)
  157.  
  158. fun loadToplevelPhrase lexbuf =
  159.   let val (phrase, isLast) = parseToplevelPhrase lexbuf in
  160.     execToplevelPhrase phrase;
  161.     isLast
  162.   end
  163. ;
  164.  
  165. fun evalUse filename =
  166.   let
  167.     val truename =
  168.       (find_in_path filename
  169.        handle Fail msg =>
  170.          (msgIBlock 0; errPrompt msg; msgEOL(); msgEBlock(); msgFlush();
  171.           raise Toplevel))
  172.     val () = (msgIBlock 0;
  173.               msgString "[opening file \""; msgString truename;
  174.               msgString "\"]"; msgEOL(); msgEBlock(); msgFlush())
  175.     val is = open_in_bin truename
  176.     val lexbuf = Compiler.createLexerStream is
  177.     fun closeIn() =
  178.       (close_in is;
  179.        msgIBlock 0;
  180.        msgString "[closing file \""; msgString truename;
  181.        msgString "\"]"; msgEOL(); msgEBlock(); msgFlush())
  182.   in
  183.     ( protect_current_input (fn () =>
  184.         (input_name := truename;
  185.          input_stream := is;
  186.          input_lexbuf := lexbuf;
  187.          while true do
  188.            let val isLast = loadToplevelPhrase lexbuf
  189.            in if isLast then raise EndOfFile else () end)))
  190.     handle
  191.         EndOfFile => closeIn()
  192.       | x => (closeIn(); raise x)
  193.   end
  194. ;
  195.  
  196. (* Compile a file *)
  197.  
  198. fun tryEvalCompile s =
  199.   protect_current_input (fn () => protectCurrentUnit (fn () =>
  200.     if Filename.check_suffix s ".sig" then
  201.       let val filename = Filename.chop_suffix s ".sig" in
  202.         compileSignature
  203.           (normalizedUnitName (Filename.basename filename))
  204.           filename
  205.       end
  206.     else if Filename.check_suffix s ".sml" then
  207.       let val filename = Filename.chop_suffix s ".sml" in
  208.         compileUnitBody
  209.           (normalizedUnitName (Filename.basename filename))
  210.           filename
  211.       end
  212.     else
  213.       raise Fail "compile: unknown file name extension"))
  214. ;
  215.  
  216. fun evalCompile s =
  217.   tryEvalCompile s
  218.   handle
  219.        Interrupt => raise Fail "compile: interrupted by the user"
  220.      | Out_of_memory => raise Fail "compile: out of memory"
  221.      | Toplevel => raise Fail "compile: error(s) in the source program"
  222. ;
  223.  
  224. (* ****************************************************** *)
  225.  
  226. (* Make.sml *)
  227. (* 05Sep95 e *)
  228.  
  229. (* portions stolen from... *)
  230.  
  231. (* Mosmldep -- computing dependencies in a Moscow ML source directory. *)
  232.  
  233. (* Lexer of stream *)
  234.  
  235. fun createLexerStream (is : instream) =
  236.   Lexing.createLexer (fn buff => fn n => Nonstdio.buff_input is buff 0 n)
  237. ;
  238.  
  239. fun parsePhraseAndClear parsingFun lexingFun lexbuf =
  240.   let val phr =
  241.     parsingFun lexingFun lexbuf
  242.     handle x => (Parsing.clearParser(); raise x)
  243.   in
  244.     Parsing.clearParser();
  245.     phr
  246.   end;
  247.  
  248. val parseFile =
  249.   parsePhraseAndClear Deppars.MLtext Deplex.Token;
  250.  
  251. fun addExt s ext = s ^ "." ^ ext;
  252.  
  253. (* now the new stuff... *)
  254.  
  255. (* 1- use Mosmldep to find each source file's dependencies
  256.    2- build some data structures (see below)
  257.    3- make the transitive closure of the dependencies
  258.    4- sort the files in dependency order
  259.    5- process each file in turn
  260.         checking modified times as documented below for function ensure
  261.         and compiling out-of-date files
  262.  
  263.   data structures...
  264.   after parsing: (objname,srcname,[objdeps],[moddeps]) called pd
  265.   closedeps calls pdltoa to make...
  266.   a hash table:   objname -> index                     called hn
  267.   and an array:   index -> pd                          called ap
  268.   and an array:   index -> [indexes of objdeps]        called di
  269.   closedeps makes
  270.       an array of indexes in dependency sorted order   called oi
  271.    and returns the value (n,hn,ap,di,oi)
  272.    where n is the length of the arrays
  273.   ensure uses n,hn,ap,di,oi to compile files needing it
  274.  
  275.   pd
  276.       objname is the name of the object file
  277.         .sml files generate .uo entry
  278.         .sig files generate .ui entry
  279.       srcname is the name of the file found in the directory
  280.       objdeps is a list of object files depended upon
  281.         dependency on a unit inserts
  282.           <unit>.ui into deps if <unit>.sig exists
  283.           otherwise <unit>.uo is inserted
  284.       moddeps is a list of units (not in this directory) depended upon
  285.  
  286.   read (the file parser) keeps a hash table of previously generated pd
  287.    it is keyed by srcname;
  288.    the modTime of the file is kept and checked to insure accuracy
  289.    this hashtable can be manually cleared with: reset_readht();
  290. *)
  291.  
  292. val moolevel = ref 1;
  293. (* moolevel
  294. 0: no messages
  295. 1: error messages
  296. 2: compile messages
  297. 3: progress messages
  298. *)
  299.  
  300. fun moo v s1 s2 = if !moolevel >= v then (say s1; say s2; say "\n") else ();
  301. fun muu v s     = if !moolevel >= v then  say s                     else ();
  302.  
  303. fun bubbleSort cmp arr =
  304.   let val sz = Array.length arr
  305.       fun swap x y =
  306.         let val x' = Array.sub(arr,x)
  307.             val y' = Array.sub(arr,y)
  308.         in Array.update(arr,x,y'); Array.update(arr,y,x') end
  309.       fun bub i =
  310.         if i >= sz then arr
  311.         else let fun sor j lo =
  312.                    if j >= sz then (swap i lo; bub (i+1))
  313.                    else if cmp(Array.sub(arr,j),Array.sub(arr,lo)) = LESS
  314.                         then sor (j+1) j
  315.                         else sor (j+1) lo
  316.                  in sor i i end
  317.       in bub 0 end;
  318.  
  319. fun pdltoa pdl =
  320.   let val hn = Hasht.new 37 : (string, int) Hasht.t
  321.       fun lp1 n r =
  322.         if (null r) then n
  323.         else let val (name,_,_,_) = (hd r)
  324.              in Hasht.insert hn name n;
  325.                 lp1 (n+1) (tl r)
  326.              end
  327.   in 
  328.     let val q  = lp1 0 pdl
  329.         val ap = Array.array(q,("","",[""],[""]))
  330.         val di = Array.array(q,[])
  331.         fun lp2 n r =
  332.           if (null r) then ()
  333.           else let val (name,_,ns,_) = (hd r)
  334.                in Array.update(ap,n,(hd r));
  335.                   Array.update(di,n,(List.map (Hasht.find hn) ns));
  336.                   lp2 (n+1) (tl r)
  337.                end
  338.     in
  339.       lp2 0 pdl;
  340.       (q,hn,ap,di)
  341.     end
  342.   end;
  343.  
  344. fun closedeps pdl =
  345.   let val (n,hn,ap,di) = pdltoa pdl
  346.       val m     = Word8.intToWord 1
  347.       val u     = Word8.intToWord 0
  348.       val fwarr = Word8Array.array (n*n,u) (* Floyd-Warshall Array *)
  349.       fun circle x =
  350.         let val (nm,_,_,_) = Array.sub (ap,x)
  351.         in moo 1 "Circularity involving: "  nm;
  352.            raise (Fail "circle"); () 
  353.         end
  354.       fun initdeps (deps,x) =
  355.         let
  356.         in List.app (fn y => Word8Array.update (fwarr,n*x+y,m)) deps;
  357.            x+1
  358.         end
  359.       fun depordr (a,b) =
  360.         if      ( (Word8Array.sub(fwarr,a*n+b)) = m ) then GREATER
  361.         else if ( (Word8Array.sub(fwarr,b*n+a)) = m ) then LESS
  362.         else EQUAL
  363.       fun kk k nk = (* transitive closure *)
  364.         if (k = n) then ()
  365.         else
  366.          let fun ii i ni =
  367.            if (i = n) then ()
  368.            else let val tik = (Word8Array.sub (fwarr, ni+k))
  369.                 in if (tik = u) then ()
  370.                    else let fun jj j =
  371.                           if (j = n) then ()
  372.                           else let val tkj = (Word8Array.sub (fwarr,nk+j))
  373.                                in if (tkj = u) then ()
  374.                                   else Word8Array.update (fwarr,ni+j,m);
  375.                                   jj (j+1)
  376.                                end
  377.                         in jj 0 end;
  378.                    ii (i+1) (ni+n)
  379.                 end
  380.          in ii 0 0; kk (k+1) (nk+n) end
  381.   in
  382.     moo 3 "\n" "Computing Dependencies";
  383.     Array.foldl initdeps 0 di;
  384.     kk 0 0;
  385.     (* check for circles
  386.        i.e., (Word8Array.sub (fwarr, ni+i)) = 1 for some i ? *)
  387.     let fun p x = if (x = n) then ()
  388.                   else let val e = Word8Array.sub (fwarr,x*n+x)
  389.                        in if (e = m) then circle x else () end
  390.     in p 0 end;
  391.     let val oi = bubbleSort depordr (Array.tabulate(n,(fn x => x)))
  392.     in (n,hn,ap,di,oi) end
  393.  end;
  394.  
  395. fun read' pdl srcext objext filename =
  396.   let val is       = open_in (addExt filename srcext)
  397.       val lexbuf   = createLexerStream is
  398.       val mentions = Hasht.new 37 : (string, unit) Hasht.t
  399.       val names    = parseFile lexbuf
  400.       val objlist = ref []
  401.       val modlist = ref []
  402.       fun adddep s =
  403.             if FileSys.access (addExt s "sig", []) then
  404.               objlist := addExt s "ui" :: !objlist
  405.             else if FileSys.access (addExt s "sml", []) then
  406.               objlist := addExt s "uo" :: !objlist
  407.         else (* libr or included dir files? *)
  408.           modlist := s :: !modlist
  409.   in 
  410.     close_in is;
  411.     List.app (fn name => Hasht.insert mentions name ()) names;
  412.     if srcext = "sml" andalso FileSys.access(addExt filename "sig", [])
  413.         then Hasht.insert mentions filename () else ();
  414.     Hasht.apply (fn name => fn _ => adddep name) mentions;
  415.     pdl := ((addExt filename objext),
  416.             (addExt filename srcext),
  417.             !objlist,
  418.             !modlist) :: !pdl
  419.   end
  420.   handle Parsing.ParseError _ => output(std_out, "Parseerror!\n");
  421.  
  422. val readht = ref (Hasht.new 67
  423.                   : (string, (Time.time *
  424.                               (string * string * string list * string list)))
  425.                   Hasht.t);
  426.  
  427. fun reset_readht _ =
  428.        readht := (Hasht.new 67
  429.                   : (string, (Time.time *
  430.                               (string * string * string list * string list)))
  431.                   Hasht.t);
  432.  
  433. fun read pdl srcext objext filename =
  434.   let val sn = (addExt filename srcext)
  435.       val mt = FileSys.modTime sn
  436.       fun dit s = muu 3 s
  437.       fun oops s =
  438.          ( dit s;
  439.            read' pdl srcext objext filename;
  440.            Hasht.insert (!readht) sn (mt,(hd (!pdl))) )
  441.   in
  442.     let val (tm,pd) = Hasht.find (!readht) sn
  443.     in
  444.       case (Time.compare (tm,mt)) of
  445.          EQUAL => ( dit "."; pdl := pd :: !pdl )
  446.        | _     => oops ";"
  447.     end
  448.     handle _ => oops ":"
  449.   end;
  450.  
  451. fun checkf srcext genext base =
  452.   let val gennam = (addExt base genext)
  453.       val havgen = (FileSys.access (gennam,[]))
  454.   in
  455.     if havgen then ()
  456.     else moo 2 "  warning: " ((addExt base srcext) ^ " but no: " ^ gennam)
  457.   end;
  458.  
  459. fun processfile pdl filename =
  460.   let val {base, ext} = Path.splitBaseExt filename
  461.       val base' = Path.file base
  462.   in 
  463.         case ext of
  464.             SOME "sig" =>  read pdl "sig" "ui" base'
  465.           | SOME "sml" =>  read pdl "sml" "uo" base'
  466.           | SOME "grm" => (checkf "grm" "sml" base'; checkf "grm" "sig" base')
  467.           | SOME "lex" =>  checkf "lex" "sml" base'
  468.           | SOME "mlp" =>  checkf "mlp" "sml" base'
  469.           | _          =>  ()
  470.   end;
  471.  
  472. fun perv_set set =
  473.   (preloadedUnits := Fnlib.lookup set preloadedUnitSets;
  474.    preopenedPreloadedUnits := Fnlib.lookup set preopenedPreloadedUnitSets)
  475.   handle Subscript =>
  476.     raise (Fail ("Unknown preloaded unit set " ^ set))
  477.  
  478. fun protect_current_options fct =
  479.   let val saved_path_library     = !path_library
  480.       and saved_load_path        = !load_path
  481.       and saved_preloadedUnits   = !preloadedUnits
  482.       and saved_poPreloadedUnits = !preopenedPreloadedUnits
  483.       and saved_watchDog         = !watchDog
  484.   (*  and saved_verbose          = !Compiler.verbose
  485.       and saved_quotation        = !Lexer.quotation     *)
  486.       and saved_write_symbols    = !Link.write_symbols
  487.       and saved_no_header        = !Link.no_header
  488.   in
  489.     (fct();
  490.      path_library            := saved_path_library;
  491.      load_path               := saved_load_path;
  492.      preloadedUnits          := saved_preloadedUnits;
  493.      preopenedPreloadedUnits := saved_poPreloadedUnits;
  494.      watchDog                := saved_watchDog;
  495.   (* Compiler.verbose        := saved_verbose;
  496.      Lexer.quotation         := saved_quotation;        *)
  497.      Link.write_symbols      := saved_write_symbols;
  498.      Link.no_header          := saved_no_header
  499.      )
  500.     handle x =>
  501.       (path_library            := saved_path_library;
  502.        load_path               := saved_load_path;
  503.        preloadedUnits          := saved_preloadedUnits;
  504.        preopenedPreloadedUnits := saved_poPreloadedUnits;
  505.        watchDog                := saved_watchDog;
  506.   (*   Compiler.verbose        := saved_verbose;
  507.        Lexer.quotation         := saved_quotation;      *)
  508.        Link.write_symbols      := saved_write_symbols;
  509.        Link.no_header          := saved_no_header;
  510.        raise x)
  511.   end
  512.  
  513. (* ensure -- that a file is compiled if need be
  514.    1- if there is no object
  515.    2- if the mtime of the object is older than the epoch
  516.    3- if the mtime of the source is newer than mtime of the object
  517.    4- if the mtime of any dependency is newer than the mtime of the object
  518.    
  519.    the build order of the files is passed in oi
  520.    trick: we keep the mtime of each object in an array, timarr, indexed
  521.           by position in the initial list; since only files earlier in
  522.           the list can be depended upon, only their times are needed, so
  523.           mtimes of files are thereby memoized
  524.    dependencies on units outside the target directory are also checked
  525.     and memoized in a local hashtable
  526. *)
  527.  
  528. fun ensure epoch (n,hn,ap,di,oi) =
  529.   let val timarr = Array.array(n,Time.zeroTime)
  530.       fun ftime x = Array.sub(timarr,x)
  531.       val itimes = Hasht.new 37 : (string, Time.time) Hasht.t
  532.       fun itime' m = 
  533.         let val uiname = (addExt m "ui")
  534.             val prname = find_in_path uiname
  535.         in moo 3 " checking: "  m;
  536.            FileSys.modTime prname
  537.         end handle Fail s => (moo 1 "  uncheck: " s; epoch)
  538.       fun itime m = Hasht.find itimes m
  539.                     handle Subscript =>
  540.                       let val i = itime' m  (* memoize! *)
  541.                       in Hasht.insert itimes m i; i end
  542.       fun nxt z =
  543.         if z >= n then ()
  544.         else let val x = Array.sub(oi,z)
  545.                  val (objname,srcname,objdeps,moddeps) = Array.sub(ap,x)
  546.                  val deps = Array.sub (di,x)
  547.              in
  548.                 if( FileSys.access (objname,[]) andalso
  549.                     let val otime = FileSys.modTime objname in
  550.                       Time.>(otime,epoch) andalso
  551.                       Time.>(otime,(FileSys.modTime srcname)) andalso
  552.                       (List.all (fn d => Time.>(otime,ftime d)) deps) andalso
  553.                       (List.all (fn d => Time.>(otime,itime d)) moddeps) andalso
  554.                       ( Array.update(timarr,x,otime); true )
  555.                     end )
  556.                 then moo 3 " ensuring: " objname
  557.                 else ( moo 2 "compiling: " objname;
  558.                        evalCompile srcname;
  559.                        Array.update(timarr,x,FileSys.modTime objname) );
  560.                 nxt (z+1)
  561.              end
  562.   in nxt 0;
  563.      moo 3 "" ""
  564.   end;
  565.  
  566. fun make oset stdlib includes path =
  567.   let open FileSys
  568.       val _   = if !moolevel < 0  (* kludgy way to reset table *)
  569.                 then (reset_readht(); moolevel := (~ (!moolevel)))
  570.                 else ()
  571.       val pdl = ref []
  572.       val dir = openDir path
  573.       val _   =   chDir path
  574.       fun read "" = ()
  575.         | read f  = ( processfile pdl f ; read (readDir dir) )
  576.       val _ = ( read (readDir dir); closeDir dir; () )
  577.               handle exn as OS.SysErr (msg, _) => (moo 1 msg ""; raise exn)
  578.       val nhnapdioi = closedeps (!pdl)
  579.   in
  580.     protect_current_options (fn () =>
  581.       (path_library := stdlib;
  582.        load_path := (if stdlib <> ""
  583.                      then includes @ [stdlib]
  584.                      else includes);
  585.        perv_set (if oset <> "" then oset else "default");
  586.        ensure Time.zeroTime nhnapdioi
  587.       ))
  588.   end;
  589.  
  590. (* lorder added 15Sep95 e *)
  591.  
  592. fun mentionsof m =
  593.   let val name  = find_in_path m (* this will raise Fail if not found *)
  594.       val is    = open_in_bin name
  595.       val stop  = input_binary_int is
  596.       val reslt = ref []
  597.   in
  598.     seek_in is stop;
  599.     let val tables = (input_value is : compiled_unit_tables)
  600.         val mentions = (#cu_mentions tables)
  601.     in
  602.       Hasht.apply
  603.         (fn key => (fn stamp => (reslt :=  (key ^ ".uo")::(!reslt))))
  604.         mentions;
  605.       close_in is;
  606.       !reslt
  607.     end
  608.     handle x => (close_in is; raise x)
  609.   end;
  610.  
  611. fun finddeps files =
  612.   let val work = ref files
  613.       val pdl  = ref []
  614.       fun have h =
  615.         if (Fnlib.member h (!work)) then true
  616.         else if (List.exists (fn (s,_,_,_) => s = h) (!pdl)) then true
  617.         else false
  618.       fun trace h =
  619.         if have h then ()
  620.         else let val ms = mentionsof h
  621.              in pdl := (h,"",ms,[])::(!pdl);
  622.                 List.app (fn x => if have x then ()
  623.                                   else work := x::(!work))  ms
  624.              end
  625.       fun loop n =
  626.         if n > 1000000 then raise (Fail "finddeps: too deep")
  627.         else
  628.           case !work of
  629.               [] => !pdl
  630.           | h::r => ( work := r; trace h; loop (n+1) )
  631.   in loop 0
  632.   end;
  633.  
  634. fun lorder files =
  635.   let val pdl = finddeps files
  636.       val (n,hn,ap,di,oi) = closedeps pdl
  637.       val reslt = ref []
  638.       fun nxt z =
  639.         if z < 0 then ()
  640.         else let val x = Array.sub(oi,z)
  641.                  val (objname,_,_,_) = Array.sub(ap,x)
  642.              in
  643.                moo 3 " linkin: " objname;
  644.                reslt := objname :: (!reslt);
  645.                nxt (z-1)
  646.              end
  647.   in
  648.     nxt (n-1);
  649.     !reslt
  650.   end;
  651.  
  652. (* *)
  653.  
  654. fun lynk exec_file (gopt,hopt) oset stdlib includes files =
  655.   protect_current_options (fn () => (protect_linker_tables (fn () =>
  656.      (path_library := stdlib;
  657.       load_path := (if stdlib <> "" then includes @ [stdlib] else includes);
  658.       let val fi = ref files
  659.       in
  660.         perv_set (case oset of
  661.                     ""       =>                      "default"
  662.                   | "lorder" => ( fi := (lorder files); "none" )
  663.                   |  _       =>                          oset );
  664.         Link.no_header      := hopt;
  665.         Link.write_symbols  := gopt;
  666.         reset_linker_tables();
  667.         watchDog := (Hasht.new 17 : (string, SigStamp) Hasht.t);
  668.         Link.link ((map (fn un => un ^".uo") (!preloadedUnits)) @ (!fi))
  669.                   exec_file;
  670.         ()
  671.       end))));
  672.  
  673. (* ****************************************************** *)
  674.  
  675. val smltop_con_basis =
  676. [
  677.   ("use",    { qualid={qual="Meta", id="use"},     info=VARname REGULARo}),
  678.   ("load",   { qualid={qual="Meta", id="load"},    info=VARname REGULARo}),
  679.   ("loadOne",{ qualid={qual="Meta", id="loadOne"}, info=VARname REGULARo}),
  680.   ("compile",{ qualid={qual="Meta", id="compile"}, info=VARname REGULARo}),
  681.   ("verbose",{ qualid={qual="Meta", id="verbose"}, info=VARname REGULARo}),
  682.   ("quotation",
  683.              { qualid={qual="Meta", id="quotation"}, info=VARname REGULARo}),
  684.   ("print",  { qualid={qual="Meta", id="print"},   info=VARname OVL1TXXo}),
  685.   ("printDepth",
  686.              { qualid={qual="Meta", id="printDepth"}, info=VARname REGULARo}),
  687.   ("printLength",
  688.              { qualid={qual="Meta", id="printLength"}, info=VARname REGULARo}),
  689.   ("chDir",  { qualid={qual="Meta", id="chDir"},     info=VARname REGULARo}), (* e *)
  690.  ("moolevel",{ qualid={qual="Meta", id="moolevel"},  info=VARname REGULARo}), (* e *)
  691.   ("make",   { qualid={qual="Meta", id="make"},      info=VARname REGULARo}), (* e *)
  692.   ("link",   { qualid={qual="Meta", id="link"},      info=VARname REGULARo}), (* e *)
  693.   ("system", { qualid={qual="Meta", id="system"},
  694.                info=PRIMname (mkPrimInfo 1 (MLPccall(1, "sml_system"))) }),
  695.   ("exit",   { qualid={qual="Meta", id="exit"},    info=VARname REGULARo}),
  696.   ("quit",   { qualid={qual="Meta", id="quit"},    info=VARname REGULARo}),
  697.   ("installPP",
  698.              { qualid={qual="Meta", id="installPP"}, info=VARname OVL1TPUo})
  699. ];
  700.  
  701. val smltop_VE =
  702. [
  703.    ("use",         trivial_scheme(type_arrow type_string type_unit)),
  704.    ("load",        trivial_scheme(type_arrow type_string type_unit)),
  705.    ("loadOne",     trivial_scheme(type_arrow type_string type_unit)),
  706.    ("compile",     trivial_scheme(type_arrow type_string type_unit)),
  707.    ("verbose",     trivial_scheme(type_ref type_bool)),
  708.    ("quotation",   trivial_scheme(type_ref type_bool)),
  709.    ("printDepth",  trivial_scheme (type_ref type_int)),
  710.    ("printLength", trivial_scheme (type_ref type_int)),
  711.    ("chDir",       trivial_scheme(type_arrow type_string type_unit)), (* e *)
  712.    ("moolevel",    trivial_scheme (type_ref type_int)),               (* e *)
  713.    ("make",        trivial_scheme(type_arrow type_string              (* e *)
  714.                                    (type_arrow type_string
  715.                                    (type_arrow (type_list type_string)
  716.                                    (type_arrow type_string type_unit))))),
  717.    ("link",        trivial_scheme(type_arrow type_string              (* e *)
  718.                                    (type_arrow (type_pair type_bool type_bool)
  719.                                    (type_arrow type_string
  720.                                    (type_arrow type_string
  721.                                    (type_arrow (type_list type_string)
  722.                                    (type_arrow (type_list type_string) type_unit))))))),
  723.    ("system",      trivial_scheme(type_arrow type_string type_int)),
  724.    ("exit",        scheme_1u (fn a => type_arrow type_int a)),
  725.    ("quit",        scheme_1u (fn a => type_arrow type_unit a))
  726. ];
  727.  
  728. val unit_smltop = newSig "Meta";
  729.  
  730. val () =
  731.   app
  732.     (fn (id, status) => Hasht.insert (#uConBasis unit_smltop) id status)
  733.     smltop_con_basis
  734. ;
  735.  
  736. val () =
  737.   app
  738.     (fn (id, sc) => Hasht.insert (#uVarEnv unit_smltop) id sc)
  739.     smltop_VE
  740. ;
  741.  
  742. val () = Hasht.insert pervSigTable "Meta" unit_smltop;
  743.  
  744. fun resetSMLTopDynEnv() =
  745.   loadGlobalDynEnv "Meta" [
  746.     ("use",         repr (evalUse: string -> unit)),
  747.     ("loadOne",     repr evalLoad),
  748.     ("load",        repr smartEvalLoad),
  749.     ("compile",     repr evalCompile),
  750.     ("verbose",     repr verbose),
  751.     ("quotation",   repr Lexer.quotation),
  752.     ("print",       repr evalPrint),
  753.     ("printDepth",  repr printDepth),
  754.     ("printLength", repr printLength),
  755.     ("chDir",       repr (fn n => FileSys.chDir n)), (* e *)
  756.     ("moolevel",    repr moolevel),                  (* e *)
  757.     ("make",        repr make),                      (* e *)
  758.     ("link",        repr lynk),                      (* e *)
  759.     ("exit",        repr (fn n => (msgFlush(); BasicIO.exit n))),
  760.     ("quit",        repr (fn () => (msgFlush(); BasicIO.exit 0))),
  761.     ("installPP",   repr evalInstallPP)
  762. ];
  763.  
  764.